﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using WindowsFormsApplication1;

namespace debugger
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        public Form1 mainForm;

        private void Form2_Load(object sender, EventArgs e)
        {
        }
        public class MemPage
        {
            public int page;
            public uint[] data = new uint[256];
        }


        MemPage[] pages = new MemPage[1+1];

        private void button1_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            mainForm.portWriteNew(0x69, 1);//nocache

            for (int j = 0; j < pages.Length; j++)
            {
                pages[j] = new MemPage();
                bool dup = true;
                while (dup)
                {
                    pages[j].page = r.Next(0x02000000 >> 10);
                    bool flg = true;
                    for (int i = 0; i < j - 1; i++)
                    {
                        if (pages[j].page == pages[i].page)
                        {
                            flg = false;
                        }
                    }
                    if (flg)
                    {
                        dup = false;
                    }
                }
                for (int i = 0; i < 1024; i += 4)
                {
                    pages[j].data[i >> 2] = (uint)r.Next();
                }

            }

            this.textBox1.Text = "";
            for (int j = 0; j < pages.Length; j++)
            {
                int pageA = pages[j].page;
                uint[] dataA = pages[j].data;
                bool err = true;
                while (err)
                {
                    bool flg = true;
                    try
                    {
                        mainForm.clearBuff();

                        for (int i = 0; i < 1024; i += 4)
                        {
                            uint addr = (uint)((pageA << 10) + i);
                            mainForm.setmem(addr, dataA[i >> 2]);
                        }
                        for (int i = 0; i < 1024; i += 4)
                        {
                            uint addr = (uint)((pageA << 10) + i);
                            uint val = mainForm.getmem(addr, null);
                            if (val != dataA[i >> 2])
                            {
                                flg = false;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        flg = false;
                    }
                    if (flg)
                    {
                        err = false;
                    }
                    else
                    {
                        this.textBox1.Text += "err";
                    }
                }
                this.textBox1.Text += "," + j;
                Application.DoEvents();
            }

            mainForm.portWriteNew(0x69, 0);//nocache

            //MessageBox.Show("ok");
        }

        private void confirm(MemPage page, int offset, StringBuilder sb)
        {
            int pageA = page.page;
            uint[] dataA = page.data;

            uint addr = (uint)((pageA << 10) + offset);
            uint val = mainForm.getmem(addr, null);
            if (sb != null)
            {
                if (val != dataA[offset >> 2])
                {
                    sb.Append(" access time:");
                    sb.Append(mainForm.getAccessTime());
                    sb.Append("addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]) + ",mem:" + Util.getHex8(val));
                    sb.AppendLine();
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            wbprep(sb, r);

            for (int j = 0; j < 1; j++)
            {
                MemPage pageA = pages[j];
                for (int i = 0; i < 512; i++)
                {
                    confirm(pageA, r.Next(128) << 2, sb);
                }

                for (int i = 0; i < 128; i++)
                {
                    confirm(pageA, i << 2, sb);
                }
                this.Text = ""+j;
                Application.DoEvents();
            }


            for (int i = 0; i < 1; i++)
            {
                int life;
                int addr;
                string invalid;
                string dirty;
                mainForm.getCacheDebugData(i, null, out addr, out life, out invalid, out dirty);
                if (life != i) {
                    this.textBox1.Text = "err1";
                    return;
                }
            }

            for (int j = 0; j < 255; j++)
            {
                confirm(pages[1], j << 2, null);
            }

            mainForm.portWriteNew((byte)(0x6A), (byte)0x00);//cache life count
            uint cache_life_count = mainForm.readFromPort();
            if (cache_life_count != 0) {
                this.textBox1.Text = "err2";
                return;
            }

            confirm(pages[1], 0, sb);

            uint flush_count = mainForm.getmem(Form1.CACHE_CTL, null);//flush count
            if (flush_count != 1)
            {
                this.textBox1.Text = "err3";
                return;
            }

            mainForm.portWriteNew(0x69, 1);//nocache
            for (int i = 0; i < 256; i++)
            {
                confirm(pages[0], i << 2, sb);
            }
            mainForm.portWriteNew(0x69, 0);//nocache

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            mainForm.portWriteNew(0x69, 0);//nocache

            int count = (int.Parse(this.textBox2.Text)*1024)/4;

            uint[] data = new uint[count];

            for (uint i = 0; i < count; i++)
            {
                uint val = (uint)r.Next();
                mainForm.setmem(i*4,val);
                //mainForm.getstatus();
                //Application.DoEvents();
                data[i] = val;
                if ((i & 255) == 0) {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }
            int err = 0;

            //mainForm.portWriteNew(0x69, 1);//nocache
            //
            //for (uint i = 0; i < count; i++)
            //{
            //    uint val = mainForm.getmem(i * 4, null);
            //    if (data[i] != val) {
            //        sb.AppendLine("a"+Util.getHex8(i * 4)+","+Util.getHex8(data[i])+","+Util.getHex8(val));
            //        err++;
            //    }
            //    if ((i & 255) == 0)
            //    {
            //        this.Text = "" + (i * 4);
            //        Application.DoEvents();
            //    }
            //}
            //
            //mainForm.portWriteNew(0x69, 0);//nocache


            err = 0;
            for (uint i = 0; i < count; i++)
            {
                uint val = mainForm.getmem(i * 4, null);
                //mainForm.getstatus();
                //Application.DoEvents();
                if (data[i] != val)
                {
                    sb.AppendLine("b" + Util.getHex8(i * 4) + "," + Util.getHex8(data[i]) + "," + Util.getHex8(val));
                    err++;
                }
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }

            this.textBox1.Text = sb.ToString();


        }

        private void button4_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            int[] points = new int[16];
            for (int i = 0; i < 16; i++)
            {
                points[i] = r.Next(256) << 2;
            }

            for (int i = 0; i < 16; i++)
            {
                confirm(pages[i], points[i], sb);
            }
            sb.AppendLine("------------1");
            {
                int j = 16;
                MemPage pageA = pages[j];

                for (int i = 0; i < 1024; i += 4)
                {
                    confirm(pageA, i, sb);
                }
            }
            sb.AppendLine("------------2");

            for (int i = 0; i < 16; i++)
            {
                int j = r.Next(256) << 2;
                confirm(pages[i], points[i], sb);
            }

            sb.AppendLine("------------3");

            for (int i = 0; i < 16; i++)
            {
                int j = r.Next(256) << 2;
                confirm(pages[i], 0, sb);
            }

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }

        private void wbprep(StringBuilder sb, Random r)
        {

            int[] points = new int[192];

            for (int j = 0; j < points.Length; j++)
            {
                bool dup = true;
                while (dup)
                {
                    points[j] = r.Next(256) << 2;
                    bool flg = true;
                    for (int i = 0; i < j - 1; i++)
                    {
                        if (points[j] == points[i])
                        {
                            flg = false;
                        }
                    }
                    if (flg)
                    {
                        dup = false;
                    }
                }
            }

            int[] bytePoses = new int[64];
            for (int j = 0; j < bytePoses.Length; j++)
            {
                bytePoses[j] = r.Next(4);
            }

            //targetpage,读取一部分，写入一部分   部分valid，部分dirty
            for (int i = 0; i < 32; i++)
            {
                confirm(pages[0], points[i], sb);
            }
            //sb.AppendLine("------------p1");

            for (int i = 64; i < 128; i++)
            {
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                uint val = (uint)r.Next();
                int offset = points[i];
                uint addr = (uint)((pageA << 10) + offset);
                dataA[offset >> 2] = val;
                mainForm.setmem(addr, val);
                //sb.AppendLine("write addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]));

            }
            //sb.AppendLine("------------p2");
            for (int i = 128; i < 192; i++)
            {
                if (i < 160)
                {
                    confirm(pages[0], points[i], sb);
                }
                int bytePos = bytePoses[i - 128];
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                int offset = points[i];
                uint addr = (uint)((pageA << 10) + offset);

                uint val = (uint)r.Next();

                mainForm.writeByteEnable(1 << bytePos);
                uint mask = ((uint)(0x0FF)) << (bytePos * 8);
                uint maskrev = ~mask;
                val &= mask;
                dataA[offset >> 2] &= maskrev;
                dataA[offset >> 2] |= val;
                mainForm.setmem(addr, val);
                //sb.AppendLine("write addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(val));
            }
            mainForm.writeByteEnable(15);

            for (int i = 0; i < 256; i++)
            {
                int pageA = pages[0].page;
                uint[] dataA = pages[0].data;
                uint addr = 0;
                int offset = 0;
                bool found = false;
                for (int j = 0; j < points.Length; j++)
                {
                    if ((points[j] >> 2) == i)
                    {
                        offset = points[j];
                        addr = (uint)((pageA << 10) + offset);
                        found = true;
                    }
                }
                if (found)
                {
                    //sb.AppendLine("writed addr:" + Util.getHex8(addr) + ",data:" + Util.getHex8(dataA[offset >> 2]));
                }
                else
                {
                    //sb.AppendLine("writed addr:" + Util.getHex8(addr) + ",data:");
                }

            }

            {
                MemPage pageA = pages[0];
                //sb.AppendLine("------------p3");
                for (int i = 64; i < 128; i++)
                {
                    confirm(pageA, points[i], sb);
                }
                //sb.AppendLine("------------p4");
                for (int i = 128; i < 160; i++)
                {
                    confirm(pageA, points[i], sb);
                }
                //sb.AppendLine("------------p5");
                for (int i = 160; i < 192; i++)
                {
                    confirm(pageA, points[i], sb);
                }
            }
        }

        //写回：
        private void button5_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            for (uint shift = 0x00080000; shift < 0x00082000; shift += 0x400)
            {

                //00002000
                uint[] data = new uint[256];

                for (uint i = 0; i < 256; i++)
                {
                    uint val = (uint)r.Next();
                    data[i] = val;
                    mainForm.setmem(i * 4 + shift, val);
                }
                for (int i = 0; i < 16; i++)
                {
                    mainForm.setmem(0x00002000 + shift, 333);
                    mainForm.setmem(0x00004000 + shift, 123);
                    mainForm.setmem(0x00006000 + shift, 333);
                }

                for (int i = 0; i < 16; i++)
                {
                    mainForm.setmem(0x00008000 + shift, 0x333);
                }

                mainForm.portWriteNew(0x69, 1);//nocache

                int err = 0;
                for (uint i = 0; i < 256; i++)
                {
                    uint val = mainForm.getmem(i * 4 + shift, null);
                    if (data[i] != val)
                    {
                        err++;
                    }
                }


                mainForm.portWriteNew(0x69, 0);//nocache

            }
            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }
        //switch back and check
        private void button6_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();


            for (int i = 0; i < 256; i++)
            {
                confirm(pages[0], i << 2, sb);
            }

            sb.AppendLine("end");
            this.textBox1.Text = sb.ToString();

        }

        private void button7_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Random r = new Random();
            mainForm.clearBuff();

            int count = (int.Parse(this.textBox2.Text) * 1024) / 4;

            uint[] data = new uint[count];
            mainForm.portWriteNew(0x69, 1);//nocache

            for (uint i = 0; i < count; i++)
            {
                uint val = (uint)r.Next();
                mainForm.setmem(i * 4, val);
                data[i] = val;
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }

            mainForm.portWriteNew(0x69, 0);//nocache



            int err = 0;
            for (uint i = 0; i < count; i++)
            {
                uint val = mainForm.getmem(i * 4, null);
                if (data[i] != val)
                {
                    sb.AppendLine("a" + Util.getHex8(i * 4) + ",T:" + Util.getHex8(data[i]) + ",F:" + Util.getHex8(val));
                    err++;
                }
                if ((i & 255) == 0)
                {
                    this.Text = "" + (i * 4);
                    Application.DoEvents();
                }
            }


            this.textBox1.Text = sb.ToString();


        }

        int status = 0; // 0 write 1 read
        int page = 0;
        int count = 0;
        int totalpage = 0;
        uint[] data;

        private void button8_Click(object sender, EventArgs e)
        {
            totalpage = int.Parse(this.textBox2.Text);
            status = 0;
            page = 0;
            count = 0;
            data = new uint[totalpage * 0x100];

            Random r = new Random();
            mainForm.portWriteNew(0x69, 1);//nocache

            for (uint i = 0; i < count * 0x100; i++)
            {
                uint val = (uint)r.Next();
                data[i] = val;
            }
            this.textBox1.Text = "";
        }

        private void button9_Click(object sender, EventArgs e)
        {
            

        }

    }
}
